/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-13
 * V4.0
 */
package com.jphenix.webserver.instancea;

import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.webserver.interfaceclass.ILog;

import javax.servlet.ServletException;
import java.io.*;
import java.util.Date;

/**
 * 日志处理类
 * 
 * 2019-09-17 整理了代码格式
 * 
 * @author 刘虻
 * 2006-9-15上午09:20:49
 */
@ClassInfo({"2019-09-17 10:37","日志处理类"})
public class Log implements ILog {

	private transient PrintStream logStream; //日志输出流
	
	private String      workPath          = System.getProperty("user.dir", "."); //工作路径
	
	private String      logEncoding       = "UTF-8";  //默认日志编码
	private String      logFileHeadName   = "phenix"; //默认日志文件头
	private String      errorLogClassName = null;     //指定错误日志流类名
	private PrintStream errorPrintStream  = null;     //指定错误日志流对象
	private boolean     isOutLog          = false;    //是否输出日志
	
	/**
	 * 构造函数
	 * 2006-9-15上午09:20:49
	 */
	public Log() {
		super();
	}

	
	/**
	 * 获取系统日志流
	 * @author 刘虻
	 * 2006-9-15上午11:22:18
	 * @return 系统日志流
	 */
	@Override
    public PrintStream getPrintStream() {

		//构造日志流
		PrintStream printstream = System.err;
		
		try {
			if (getLogEncoding() != null) {
				printstream = new PrintStream(
						//构造文件输出对象
						new FileOutputStream(
								new File(
										getWorkPath()
										,getLogFileHeadName()
											+System.currentTimeMillis()
											+ ".log")),true,getLogEncoding());
			}else {
				printstream = 
					new PrintStream(
							new FileOutputStream(
									new File(
											getWorkPath()
											,getLogFileHeadName()
												+System.currentTimeMillis()
												+".log")),true);
			}
			if (getErrorPrintStream() != null)
				//设置指定错误流对象
            {
                System.setErr(getErrorPrintStream());
            } else {
                System.setErr(printstream);
            }
		} catch (IOException e) {
			System.err.println("I/O problem at setting a log stream " + e);
		}
		return printstream;
	}
	
	/**
	 * 是否输出普通日志
	 * @author 刘虻
	 * 2008-6-29下午09:47:18
	 * @param isOutLog 是否输出普通日志
	 */
	@Override
    public void setOutLog(boolean isOutLog) {
		this.isOutLog = isOutLog;
	}
	
	/**
	 * 输出日志
	 * @author 刘虻
	 * 2006-9-15上午09:25:47
	 * @param message 日志信息
	 */
	@Override
    public void log(String message) {
		if (isOutLog) {
			Date date = new Date(System.currentTimeMillis());
			getLogStream().println("[" + date.toString() + "] " + message);
		}
	}

	/**
	 * 输出日志
	 * @author 刘虻
	 * 2006-9-15上午09:39:17
	 * @param message 日志信息
	 * @param throwable 断点对象
	 */
	@Override
    public void log(String message, Throwable throwable) {
		if (throwable != null) {
			StringWriter sw;
			PrintWriter pw = new PrintWriter(sw = new StringWriter());
			throwable.printStackTrace(pw);
			printCauses(throwable, pw);
			message = message + '\n' + sw;
		}
		log(message);
	}
	
	
	
	/**
	 * 打印异常来源
	 * @author 刘虻
	 * 2006-9-15上午09:45:38
	 * @param throwable 异常来源
	 * @param printWriter 输出流
	 */
	protected void printCauses(
			Throwable throwable
			,PrintWriter printWriter) { 
			try { 
				if (throwable instanceof ServletException) {
					throwable = ((ServletException)throwable).getRootCause();
				}else {
					throwable = (Throwable) throwable.getClass().getMethod(
							"getCause").invoke(throwable, new Object[]{});
				}
				if (throwable != null) { 
					printWriter.write("Caused by:\n"); 
					throwable.printStackTrace(printWriter); 
					printCauses(throwable, printWriter); 
				} 
			} catch(Exception e) {} 
	}


	/**
	 * 输入异常日志
	 * @author 刘虻
	 * 2006-9-15上午09:44:51
	 * @param exception 异常对象
	 * @param message 日志信息
	 */
	@Override
    public void log(Exception exception, String message) {
		log(message, exception);
	}

	
	/**
	 * 获取日志流
	 * @author 刘虻
	 * 2007-9-30下午02:47:41
	 * @return 日志流
	 */
	@Override
    public PrintStream getLogStream() {
		if (logStream==null) {
			System.err.println("the log PrintStream kernel not init");
		}
		return logStream;
	}


	/**
	 * 设置日志流
	 * @author 刘虻
	 * 2007-9-30下午02:47:54
	 * @param logStream 日志流
	 */
	@Override
    public void setLogStream(PrintStream logStream) {
		this.logStream = logStream;
	}


	/**
	 * 获取日志编码
	 * @author 刘虻
	 * 2007-9-30下午02:48:02
	 * @return 日志编码
	 */
	@Override
    public String getLogEncoding() {
		return logEncoding;
	}

	/**
	 * 设置日志编码
	 * @author 刘虻
	 * 2007-9-30下午02:48:18
	 * @param logEncoding 日志编码
	 */
	@Override
    public void setLogEncoding(String logEncoding) {
		this.logEncoding = logEncoding;
	}



	/**
	 * 获取工作路径
	 * @author 刘虻
	 * 2007-9-30下午02:48:27
	 * @return 工作路径
	 */
	@Override
    public String getWorkPath() {
		return workPath;
	}



	/**
	 * 设置工作路径
	 * @author 刘虻
	 * 2007-9-30下午02:48:47
	 * @param workPath 工作路径
	 */
	@Override
    public void setWorkPath(String workPath) {
		this.workPath = workPath;
	}

	/**
	 * 获取普通日志文件头名
	 * @author 刘虻
	 * 2007-9-30下午02:48:54
	 * @return 普通日志文件头名
	 */
	@Override
    public String getLogFileHeadName() {
		return logFileHeadName;
	}

	/**
	 * 设置普通日志文件头名
	 * @author 刘虻
	 * 2007-9-30下午02:49:12
	 * @param logFileHeadName 普通日志文件头名
	 */
	@Override
    public void setLogFileHeadName(String logFileHeadName) {
		this.logFileHeadName = logFileHeadName;
	}



	/**
	 * 获取错误日志类名
	 * @author 刘虻
	 * 2007-9-30下午02:49:58
	 * @return 错误日志类名
	 */
	@Override
    public String getErrorLogClassName() {
		return errorLogClassName;
	}


	/**
	 * 设置错误日志类名
	 * @author 刘虻
	 * 2007-9-30下午02:50:10
	 * @param errorLogClassName 错误日志类名
	 */
	@Override
    public void setErrorLogClassName(String errorLogClassName) {
		this.errorLogClassName = errorLogClassName;
	}


	/**
	 * 获取错误日志流
	 * @author 刘虻
	 * 2007-9-30下午02:50:17
	 * @return 错误日志流
	 */
	@Override
    public PrintStream getErrorPrintStream() {
		if (errorPrintStream==null || errorPrintStream.checkError()) {
			if (getErrorLogClassName()!=null 
					&& getErrorLogClassName().length()>0) {
				try {
					//构造指定错误信息流对象
					errorPrintStream = 
						(PrintStream) Class.forName(
								getErrorLogClassName()).newInstance();
				}catch(Exception e) {
					e.printStackTrace();
				}
			}
		}
		return errorPrintStream;
	}


	/**
	 * @deprecated 不赞成使用，如果设置进来的流对象被别的类方法关闭了，或者为空
	 * 就会导致失败
	 * @param errorPrintStream 要设置的 errorPrintStream
	 */
    @Override
    public void setErrorPrintStream(PrintStream errorPrintStream) {
		this.errorPrintStream = errorPrintStream;
	}

	
	
	
	
}
